import { request } from '@tarojs/taro';
import ip from './server';
import AxiosRequestConfig from './type';

/** 不再兼容非标准的数据结构 */
export declare type AjaxPromise2<R> = Promise<R>;
/** 非标准包裹 */
export declare type AjaxPromise<R> = Promise<{
  statusCode?: number;
  errMsg?: string;
  data: R;
}>;
export interface ExtraFetchParams {
  /** extra data for extends */
  extra?: any;
  /** 扩展请求头 */
  headers?: any;
  /** cancel request */
  cancel?: Promise<string | undefined>;
}
export interface WrappedFetchParams extends ExtraFetchParams {
  /** http method */
  method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'PATCH' | 'HEAD';
  url: string;
  /** post json data */
  data?: any;
  /** post form data */
  form?: any;
  /** query data */
  query?: any;
  /** header */
  header?: any;
  /** path data */
  path?: any;
}

// export const fetch = axios;
export const fetch = request;

const ajax = {
  /** ajax 方法 */
  ajax(param: WrappedFetchParams): Promise<any> {
    const { method, url, data, form, query, header, extra, headers } = param;

    let config: AxiosRequestConfig = {
      ...extra,
      method: method.toLowerCase(),
      header: { ...headers, ...header },
    };

    // json
    if (data) {
      config = {
        ...config,
        header: {
          // 可覆盖
          'Content-Type': 'application/json',
          ...config.header,
        },
        data,
      };
    }

    if (query) {
      config = {
        ...config,
        data: query,
      };
    }

    // form
    if (form) {
      config = {
        ...config,
        data: form,
      };
    }

    // 下载
    if (extra?.download) {
      config = {
        ...config,
        responseType: 'arraybuffer',
      };
    }
    const path = ip.ip ? ip.ip + url : url;

    return request({
      ...config,
      url: path,
      timeout: 10000,
    }).then((response) => {
      //先判断网络请求
      if (Math.floor(response.statusCode / 100) !== 2) {
        throw new Error(`${response.errMsg}`);
      }

      if (extra?.download) {
        // 包装成文件

        // 获取文件名
        let filename = '';
        const contentDisposition = String(response.header['content-disposition'] ?? '');
        for (const part of contentDisposition.split(/;(?: *)/)) {
          const [k, v] = part.split('=');
          // 优先用 filename*，其次 filename
          if (k === 'filename*') {
            filename = v;
            break;
          } else if (k === 'filename') {
            filename = v;
          }
        }
        // decode url-encoded
        filename = decodeURIComponent(filename);

        const file = new File([response.data], filename, {
          type: 'text/plain',
        });

        return file;
      }

      return response.data;
    });
  },

  check<V>(value: V, name: string): void {
    // TODO 把接口验证挪到这里来？
  },
};

export default ajax;
